package cheme.ProcessEditor.Parts.Streams.Tag;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.draw2d.Connection;
import org.eclipse.draw2d.Cursors;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.ImageFigure;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.MouseEvent;
import org.eclipse.draw2d.MouseListener;
import org.eclipse.draw2d.PositionConstants;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.gef.ConnectionEditPart;
import org.eclipse.gef.DragTracker;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.Request;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.tools.SimpleDragTracker;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.Image;

import cheme.ProcessEditor.ChemeConstants;
import cheme.ProcessEditor.LeafFigureNavigator;
import cheme.ProcessEditor.Figures.DecoratableFigure;
import cheme.ProcessEditor.Figures.TagFig;
import cheme.ProcessEditor.Figures.Util.MoveTagCmd;
import cheme.ProcessEditor.Figures.Util.TagLocator;
import cheme.ProcessEditor.Figures.Util.TitleFig;
import cheme.ProcessEditor.Parts.Streams.TagDragTracker;
import cheme.ProcessEditor.Table.AbstractTablePart;
import cheme.ProcessEditor.Table.ListLineFig;
import cheme.ProcessEditor.Table.SubTableFig;
import cheme.ProcessEditor.Table.TableHeaderDecoration;
import cheme.ProcessEditor.Table.TableRowFig;
import cheme.ProcessEditor.Util.SelectionHelper;
import cheme.ProcessModel.ProcessUnits.Streams.Tags.Tag;

public class PartTag extends AbstractTablePart
{
	TagFig expandedTag = null;
	TagFig collapsedTag = null;
	ListLineFig header = null;
	
	SubTableFig contentPane = null;
	
	TagLocator locator = null;

	protected static final Image collapseImage = ChemeConstants.DESC_COLLAPSE.createImage();
	protected static final Image expandImage = ChemeConstants.DESC_EXPAND.createImage();
	
	/*
	 * Pretty complicated figure here. In this builder method, a couple simple listeners are attached to
	 * a 'collapse/expand' figure that triggers the hiding and showing of the full tag elements.
	 */
	@Override
	protected DecoratableFigure<TagFig> createFigure()
	{		
		/*
		 * Setup the expanded looking tag thingy.
		 */
		expandedTag = new TagFig();
		DecoratableFigure<TagFig> decoratedTable = new DecoratableFigure<TagFig>(expandedTag);

		TableHeaderDecoration<SubTableFig> header = new TableHeaderDecoration<SubTableFig>();
		
		final TableRowFig expandedHeader = new TableRowFig();
		expandedHeader.add(new TitleFig("Label"));
		expandedHeader.add(new TitleFig("Quantity"));
		expandedHeader.add(new TitleFig("Units"));
		expandedHeader.add(new TitleFig("Compound"));
		
		final ImageFigure collapseFig = new ImageFigure(collapseImage);
		collapseFig.addMouseListener(new MouseListener()
		{
			public void mousePressed(MouseEvent me)
			{
				/*
				 * Actually perform the 'expand' or swapping of figures.
				 */
				
				expandedHeader.remove(collapseFig);
				getFigure().setContentPane(collapsedTag);
			}

			public void mouseDoubleClicked(MouseEvent me) {}
			public void mouseReleased(MouseEvent me) {}
		});
		
		collapseFig.setToolTip(new Label("Collapse Tag\nPress to minimize this tag."));
		expandedHeader.add(collapseFig);
		
		
		header.setHeader(expandedHeader);

		contentPane = new SubTableFig(); //the list of tag componenents will sit here.
		header.setContentPane(contentPane);

		expandedTag.add(header);
			
		/*
		 * Setup the collapsed tag.
		 */
		
		collapsedTag = new TagFig();
		final TableRowFig collapsedHeader = new TableRowFig();
		TitleFig ellipsis = new TitleFig("...");
		ellipsis.setToolTip(expandedTag);
		collapsedHeader.add(ellipsis);
		
		final ImageFigure expandFig = new ImageFigure(expandImage);
		expandFig.addMouseListener(new MouseListener()
		{
			public void mousePressed(MouseEvent me)
			{
				/*
				 * Actually perform the 'collapse' or swapping of figures.
				 */
				
				expandedHeader.add(collapseFig);
				getFigure().setContentPane(expandedTag);
			}

			public void mouseDoubleClicked(MouseEvent me) {}
			public void mouseReleased(MouseEvent me) {}
		});
		
		expandFig.setToolTip(new Label("Expand Tag\nPress to expand this tag."));
		collapsedHeader.add(expandFig);
		
		
		collapsedTag.add(collapsedHeader);
			
			
		return decoratedTable;
	}

	@Override
	protected void createEditPolicies()
	{
		installEditPolicy(EditPolicy.COMPONENT_ROLE, new PolicyTag());
//		installEditPolicy(EditPolicy.LAYOUT_ROLE, new PolicyTagLayout());
//		installEditPolicy(EditPolicy.LAYOUT_ROLE, new FigureDropPolicy());
	}

	public Tag getModel()
	{
		return (Tag)super.getModel();
	}

	public DecoratableFigure<TagFig> getFigure()
	{
		return (DecoratableFigure<TagFig>)super.getFigure();
	}
	
	@Override
	public IFigure getContentPane()
	{
		return contentPane;
	}
	
	@Override
	protected void addChild(EditPart child, int index)
	{
		super.addChild(child, index);
		
		GraphicalEditPart navigateFrom = SelectionHelper.getFirstLeaf((GraphicalEditPart)child);
		
		if(null != navigateFrom)
		{
			LeafFigureNavigator.navigateTo(navigateFrom);
		}
	}
	
	@Override
	protected void removeChild(EditPart child)
	{
		/*
		 * If the child being remove had primary focus, we navigate to the 
		 * nearest neighbor above. This is a nicety for table-like editing in the
		 * stream descriptor.
		 */
		GraphicalEditPart navigateFrom = SelectionHelper.getFirstLeaf((GraphicalEditPart)child); 
		
		if(null != navigateFrom)
		{
			LeafFigureNavigator.navigateNearestSibling(navigateFrom, PositionConstants.NORTH);
		}
		
		super.removeChild(child);
	}
	
	/*
	 * Returns a new locator of the type appropriate for this class.
	 */
	public TagLocator getLocator()
	{
		return locator;
	}
	
	public void setLocator(TagLocator locator)
	{
		this.locator = locator;
	}
	
	@Override
	public DragTracker getDragTracker(Request request)
	{
		return new TagDragTracker(this, (ConnectionEditPart)getParent());
	}
	
//	class TagDragTracker extends SimpleDragTracker //DragEditPartsTracker
//	{
//		private Object type;
//		EditPart sourceEditPart;
//		private ConnectionEditPart editpart;
//		
//		public TagDragTracker(EditPart sourceEditPart, ConnectionEditPart Connection)
//		{
////			super(sourceEditPart);
//			setConnectionEditPart(Connection);
//			this.sourceEditPart = sourceEditPart;
//			setType(ChemeConstants.REQUEST_MOVE_TAG);
//		}
//		
//		public void setConnectionEditPart(ConnectionEditPart cep)
//		{
//			editpart = cep;
//		}
//		
//		protected List createOperationSet()
//		{
//			List list = new ArrayList();
//			list.add(getConnectionEditPart());
//			return list;
//		}
//		
//		protected ConnectionEditPart getConnectionEditPart() {
//			return editpart;
//		}
//		
//		protected Connection getConnection() {
//			return (Connection)getConnectionEditPart().getFigure();
//		}
//
//		public void setType(Object type)
//		{
//			this.type = type;
//		}
//		
//		/*
//		 *  The type of tracker, either {@link RequestConstants#REQ_CREATE_BENDPOINT} or
//		 * {@link RequestConstants#REQ_MOVE_BENDPOINT}.
//		 * @return the type of operation being performed (move or create bendpoint)
//		 */
//		protected Object getType() {
//			return type;
//		}
//		
//		@Override
//		protected Cursor getDefaultCursor()
//		{
//			return Cursors.ARROW;
//		}
//
//		@Override
//		protected Command getCommand()
//		{
//			Dimension delta = getDragMoveDelta();
//			int newX = locator.getXGap() + delta.width;
//			int newY = locator.getYGap() + delta.height;
//
//			return new MoveTagCmd(getFigure(), locator, newX, newY);
//		}
//
//		protected void setCurrentCommand(Command c)
//		{
//			super.setCurrentCommand(c);
//		}
//
//		protected void executeCurrentCommand()
//		{
//			Command curCommand = getCurrentCommand();
//			if(curCommand != null && curCommand.canExecute())
//				executeCommand(curCommand);
//			setCurrentCommand(null);
//		}
//
//		@Override
//		protected String getCommandName()
//		{
//			return null;
//		}
//		
//		@Override
//		protected void updateSourceRequest()
//		{
//			getSourceRequest();
//			super.updateSourceRequest();
//		}
//	};
}
